﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Collections;
using System.Net;

using Microsoft.Web.Administration;

using King.Extensions;
using King.Reflection;
using King.Text;
using King.Automation;
using King.Declarative;

namespace King.InternetInformationService {

    public class Program {
        public static int Main(string[] args) {
            return ComandConsoleApplication.EntryPoint(args);
        }
    }
    public struct IisContext {

        public static implicit operator IisContext(DeclarationContext context) {
            return new IisContext(context);
        }

        private DeclarationContext m_context;

        internal IisContext(DeclarationContext context) {
            m_context = context;
        }

        public ServerManager ServerManager {
            get { return m_context.Ancestors<IisRoot>().Single().ServerManager; }
        }
    }

    [Declaration(UseDedicatedStack = true, SubstituteTypes = typeof(bool))]
    internal sealed class IisRoot : Declaration {

        private ServerManager m_serverManager;

        internal IisRoot() {
        }

        internal ServerManager ServerManager {
            get {
                if (m_serverManager == null)
                    m_serverManager = new ServerManager();
                return m_serverManager;
            }
        }
        protected override IEnumerable Substitute(DeclarationContext frame, object target) {
            return (bool)target ? "true" : "false";
        }
    }

    [Declaration(AdaptorType = typeof(Adaptor))]
    public abstract class IisCommand : Command {

        protected new class Adaptor : GenericDeclaration.Adaptor {

            public Adaptor(Type adaptedType)
                : base(adaptedType) {
            }

            public override object Prolog(DeclarationContext frame, object value) {

                if (!(frame.IsEvaluating))
                    return null;

                if (value is IisRoot)
                    return null;

                if (frame.Ancestors(typeof(IisRoot)).Any())
                    return null;

                return new IisRoot { value };
            }
        }

        internal IisCommand(params object[] arguments)
            : base(arguments) {
        }

        protected IEnumerable<ApplicationPool> ApplicationPools(ServerManager manager, string name) {
            var pools =
                from o in manager.ApplicationPools
                orderby o.Name
                where name == null || o.Name.CaseInsensitveEquals(name)
                select o;

            if (pools.None())
                throw new ArgumentException("Application pool not found.");

            return pools;
        }
        protected ApplicationPool GetApplicationPool(ServerManager manager, string name) {
            return ApplicationPools(manager, name).Single();
        }
        protected IEnumerable<Site> Sites(ServerManager manager, string name) {
            var sites =
                from o in manager.Sites
                orderby o.Name
                where name == null || o.Name.CaseInsensitveEquals(name)
                select o;

            if (sites.None())
                throw new ArgumentException("Site not found.");

            return sites;
        }
        protected Site GetSite(ServerManager manager, string name) {
            return Sites(manager, name).Single();
        }
    }
}
